﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Xml;
using System.Threading;
using System.Text.RegularExpressions;
using HtmlAgilityPack;

namespace FreeKickManager
{
    public partial class FrmVisorPartidos : Form
    {
        private List<ReportePartido> reportes = null;
        private ReportePartido reportePropio = null;

        private int minuto = 1;
        private bool pausa = false;

        private string categoria = "";

        private int tiempoMinuto = 0;
        private int tiempoJugada = 0;

        private Partido partidoPropio = null;


        public FrmVisorPartidos()
        {
            InitializeComponent();

            reportes = new List<ReportePartido>();
        }

        public FrmVisorPartidos(Partido part)
        {
            InitializeComponent();

            this.categoria = "";
            this.partidoPropio = part;
        }

        public FrmVisorPartidos(string categoria)
        {
            InitializeComponent();

            reportes = new List<ReportePartido>();

            this.categoria = categoria; //senior ó youth
            this.partidoPropio = null;

            //Tiempos
            tiempoMinuto = Convert.ToInt32(FrmPrincipal.opciones.obtenerOpcion("tiempoMinuto"));
            tiempoJugada = Convert.ToInt32(FrmPrincipal.opciones.obtenerOpcion("tiempoJugada"));
        }

        private void cargaPartido()
        {
            CargadorXml.descargarXml("http://www.freekick.org/public/getdata.php?getdata=matchreport&datatype=xml&id=" + partidoPropio.id, "temp\\partido.xml");

            bwWorkerCarga.ReportProgress(1);

            reportePropio = CargadorXml.cargarReporte(partidoPropio, "temp\\partido.xml");

            bwWorkerCarga.ReportProgress(1);

            generarHtml(reportePropio);

            bwWorkerCarga.ReportProgress(1);

            wbAlineacionInicial.Navigate(Application.StartupPath + "\\temp\\alineacion-inicial.html");
            wbAlineacionFinal.Navigate(Application.StartupPath + "\\temp\\alineacion-final.html");

            bwWorkerCarga.ReportProgress(1);

            wbPartido.Navigate(Application.StartupPath + "\\temp\\reporte.html");

            bwWorkerCarga.ReportProgress(1);
        }

        private void cargarPartidosDirecto()
        {
            string xml = null;

            List<Equipo> equiposGrupo = new List<Equipo>();
            List<Partido> listaPartidos = new List<Partido>();

            if (FrmPrincipal.infoEquipo == null)
            {
                //Obtenemos los datos del grupo de liga de mi equipo
                xml = CargadorXml.descargarXml(@"http://www.freekick.org/public/getdata.php?getdata=ownclub&datatype=xml&username=" + FrmPrincipal.opciones.obtenerOpcion("usuario") + "&password=" + FrmPrincipal.opciones.obtenerOpcion("password"));

                if (xml != null)
                {
                    FrmPrincipal.infoEquipo = CargadorXml.cargarInformacionEquipo(xml);
                }
            }

            bwWorkerCarga.ReportProgress(1);

            //Obtenemos el último partido de mi equipo
            xml = CargadorXml.descargarXml("http://www.freekick.org/public/getdata.php?getdata=matches&type=league&squad=" + categoria + "&teamid=" + FrmPrincipal.infoEquipo.idEquipo + "&lastgames=1&played=true");

            if (xml != null)
            {
                List<Partido> misPartidos = CargadorXml.cargarListaPartidos(xml);

                listaPartidos.Add(misPartidos[0]);

                partidoPropio = misPartidos[0];
            }

            bwWorkerCarga.ReportProgress(1);

            if (FrmPrincipal.clasifSenior == null || FrmPrincipal.clasifJuvenil == null)
            {
                //Obtenemos la lista de equipos de mi grupo
                if (categoria.Equals("senior"))
                {
                    xml = CargadorXml.descargarXml(@"http://www.freekick.org/public/getdata.php?getdata=league&datatype=xml&league=" + FrmPrincipal.infoEquipo.liga + "&division=" + FrmPrincipal.infoEquipo.divisionSenior + "&series=" + FrmPrincipal.infoEquipo.serieSenior + "&squad=" + categoria + "&season=" + partidoPropio.temporada);
                }
                else
                {
                    xml = CargadorXml.descargarXml(@"http://www.freekick.org/public/getdata.php?getdata=league&datatype=xml&league=" + FrmPrincipal.infoEquipo.liga + "&division=" + FrmPrincipal.infoEquipo.divisionJuvenil + "&series=" + FrmPrincipal.infoEquipo.serieJuvenil + "&squad=" + categoria + "&season=" + partidoPropio.temporada);
                }

                if (xml != null)
                {
                    equiposGrupo = CargadorXml.cargarClasificacion(xml);
                }
            }
            else
            {
                if (categoria.Equals("senior"))
                {
                    equiposGrupo = FrmPrincipal.clasifSenior;
                }
                else
                {
                    equiposGrupo = FrmPrincipal.clasifJuvenil;
                }
            }

            bwWorkerCarga.ReportProgress(1);

            //Para cada equipo obtenemos su último partido
            foreach (Equipo eq in equiposGrupo)
            {
                //Si no es mi equipo...
                if (eq.id != FrmPrincipal.infoEquipo.idEquipo)
                {
                    xml = CargadorXml.descargarXml("http://www.freekick.org/public/getdata.php?getdata=matches&type=league&squad=" + categoria + "&teamid=" + eq.id + "&lastgames=1&played=true");

                    if (xml != null)
                    {
                        List<Partido> ultimosPartidos = CargadorXml.cargarListaPartidos(xml);

                        //Añadimos el partido si aún no estaba en la lista
                        if (listaPartidos.IndexOf(ultimosPartidos[0]) == -1)
                        {
                            listaPartidos.Add(ultimosPartidos[0]);
                        }
                    }
                }
            }

            bwWorkerCarga.ReportProgress(1);

            //Obtenemos los reportes de los partidos
            foreach (Partido part in listaPartidos)
            { 
                CargadorXml.descargarXml("http://www.freekick.org/public/getdata.php?getdata=matchreport&datatype=xml&id=" + part.id, "temp\\partido.xml");

                ReportePartido rep = CargadorXml.cargarReporte(part, "temp\\partido.xml");

                reportes.Add(rep);

                if (rep.partido.id.Equals(partidoPropio.id))
                {
                    reportePropio = rep;
                }
            }

            //Generamos los HTML de las alineaciones y el reporte
            generarHtml(reportePropio);

            //Cargar los HTML
            wbAlineacionInicial.Navigate(Application.StartupPath + "\\temp\\alineacion-inicial.html");
            wbAlineacionFinal.Navigate(Application.StartupPath + "\\temp\\alineacion-final.html");
            wbPartido.Navigate(Application.StartupPath + "\\temp\\reporte.html");

            bwWorkerCarga.ReportProgress(1);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Play

            pausa = false;
            bwWorker.RunWorkerAsync();

            btnReproducir.Enabled = false;
            btnPausa.Enabled = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            //Pausa

            pausa = true;

            btnReproducir.Enabled = true;
            btnPausa.Enabled = false;
        }

        private void bwWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            //Primera parte
            for (int min = minuto; min <= 45; min++)
            {
                //Si se ha pulsado el botón de Pausa salimos del bucle
                if (pausa)
                    break;

                //Comenzamos el minuto actual
                bwWorker.ReportProgress(0, new EventoReporte(minuto,""));

                //Buscamos las ocasiones de mi partido en el minuto actual
                List<Ocasion> ocasionesMinuto = reportePropio.buscarOcasiones(minuto);

                foreach (Ocasion oc in ocasionesMinuto)
                {
                    bwWorker.ReportProgress(1, new EventoReporte(minuto, "Minuto " + oc.minuto));

                    foreach (string jugada in oc.jugadas)
                    {
                        bwWorker.ReportProgress(1, new EventoReporte(minuto, jugada));

                        Thread.Sleep(tiempoJugada);
                    }

                    bwWorker.ReportProgress(1, new EventoReporte(minuto, ""));
                }


                //Buscamos las ocasiones del minuto de juego actual para cada partido del grupo
                foreach(ReportePartido rep in reportes)
                {
                    ocasionesMinuto = rep.buscarOcasiones(min);

                    //Buscamos si hay goles en las ocasiones
                    foreach (Ocasion oc in ocasionesMinuto)
                    {
                        if (oc.existeEnJugadas("¡GOL!"))
                        {
                            //Reportamos el gol
                            EventoReporte ev = new EventoReporte(minuto, "Min " + minuto + ": " + rep.partido.ToString() + " " + oc.jugadas[oc.jugadas.Count - 1]);
                            bwWorker.ReportProgress(0, ev);
                        }
                    }
                }

                //Incrementamos el minuto actual
                Thread.Sleep(tiempoMinuto);
                minuto++;
            }

            
            //Intermedio
            if(!pausa)
                bwWorker.ReportProgress(0, new EventoReporte(minuto, "DESCANSO PARTIDOS"));


            //Incrementamos el minuto actual
            Thread.Sleep(tiempoMinuto);

            //Segunda parte
            for (int min = minuto; min <= 90; min++)
            {
                //Si se ha pulsado el botón de Pausa salimos del bucle
                if (pausa)
                    break;

                //Comenzamos el minuto actual
                bwWorker.ReportProgress(0, new EventoReporte(minuto, ""));

                //Buscamos las ocasiones de mi partido en el minuto actual
                List<Ocasion> ocasionesMinuto = reportePropio.buscarOcasiones(minuto);

                foreach (Ocasion oc in ocasionesMinuto)
                {
                    bwWorker.ReportProgress(1, new EventoReporte(minuto, "Minuto " + oc.minuto));

                    foreach (string jugada in oc.jugadas)
                    {
                        bwWorker.ReportProgress(1, new EventoReporte(minuto, jugada));

                        Thread.Sleep(tiempoJugada);
                    }

                    bwWorker.ReportProgress(1, new EventoReporte(minuto, ""));
                }

                //Buscamos las ocasiones del minuto de juego actual para cada partido
                foreach (ReportePartido rep in reportes)
                {
                    ocasionesMinuto = rep.buscarOcasiones(min);

                    //Buscamos si hay goles en las ocasiones
                    foreach (Ocasion oc in ocasionesMinuto)
                    {
                        if (oc.existeEnJugadas("¡GOL!"))
                        {
                            //Reportamos el gol
                            EventoReporte ev = new EventoReporte(minuto, "Min " + minuto + ": " + rep.partido.ToString() + " " + oc.jugadas[oc.jugadas.Count - 1]);
                            bwWorker.ReportProgress(0, ev);
                        }
                    }
                }

                //Incrementamos el minuto actual
                Thread.Sleep(tiempoMinuto);
                minuto++;
            }
        }

        private void bwWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            EventoReporte ev = (EventoReporte)e.UserState;

            if (e.ProgressPercentage == 0)
            {
                lblMinuto.Text = ev.minuto.ToString();

                if (!ev.evento.Equals(""))
                    lstEventos.Items.Add(ev.evento);
            }
            else 
            {
                lstReporte.Items.Add(ev.evento);
                lstReporte.SetSelected(lstReporte.Items.Count - 1, true);
                lstReporte.SetSelected(lstReporte.Items.Count - 1, false);
            }
        }

        private void bwWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(!pausa)
                lstEventos.Items.Add("FIN PARTIDOS");
        }

        private void lstReporte_DrawItem(object sender, DrawItemEventArgs e)
        {
            Graphics g = e.Graphics;

            SolidBrush br = new SolidBrush(Color.Black);
            string s = "";

            try
            {
                s = lstReporte.Items[e.Index].ToString();
            }
            catch(Exception)
            {
                s = "";
            }

            if ((e.State & DrawItemState.Selected) != 0)
            {
                g.FillRectangle(Brushes.LightBlue, e.Bounds);
                g.DrawRectangle(Pens.DarkBlue, e.Bounds);
            }
            else
            {
                g.FillRectangle(Brushes.White, e.Bounds);
            }

            Font f = null;
            if (s.StartsWith("Minut"))
                f = new Font(lstReporte.Font, FontStyle.Bold);
            else
                f = lstReporte.Font;

            g.DrawString(s, f, br, e.Bounds);
        }

        private void lstReporte_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            Graphics g = e.Graphics;
            string s = "";

            try
            {
                s = lstReporte.Items[e.Index].ToString();
            }
            catch (Exception)
            {
                s = "";
            }

            SizeF sz = g.MeasureString(s, lstReporte.Font, lstReporte.Width - 5 - SystemInformation.VerticalScrollBarWidth);

            e.ItemHeight = (int)sz.Height + 5;
            e.ItemWidth = (int)sz.Width + 15;
        }

        private void bwWorkerCarga_DoWork(object sender, DoWorkEventArgs e)
        {
            if (partidoPropio == null)
                cargarPartidosDirecto();
            else
                cargaPartido();
        }

        private void bwWorkerCarga_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pbCargaJornada.PerformStep();
        }

        private void bwWorkerCarga_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //Se actualizan los nombres de los equipos en los gráficos de alineación
            lblLocal.Text = partidoPropio.campo.Equals("home") ? partidoPropio.nombrePropio : partidoPropio.nombreOponente;
            lblVisitante.Text = partidoPropio.campo.Equals("home") ? partidoPropio.nombreOponente : partidoPropio.nombrePropio;

            lblLocalFinal.Text = partidoPropio.campo.Equals("home") ? partidoPropio.nombrePropio : partidoPropio.nombreOponente;
            lblVisitanteFinal.Text = partidoPropio.campo.Equals("home") ? partidoPropio.nombreOponente : partidoPropio.nombrePropio;

            //Se actualizan los gráficos de alineación
            foreach (Jugador j in reportePropio.titularesLocal)
            {
                luInicialLocal.addObject(new FKLineup.CirclePlayer(j, 10, 10, 10, 10));
            }

            foreach (Jugador j in reportePropio.titularesVisitante)
            {
                luInicialVisitante.addObject(new FKLineup.CirclePlayer(j, 10, 10, 10, 10));
            }

            foreach (Jugador j in reportePropio.titularesLocalFin)
            {
                Jugador jAux = j.clonar();
                jAux.posicion = jAux.posicion.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[0].Trim();

                luLocalFinal.addObject(new FKLineup.CirclePlayer(jAux, 10, 10, 10, 10));
            }

            foreach (Jugador j in reportePropio.titularesVisitanteFin)
            {
                Jugador jAux = j.clonar();
                jAux.posicion = jAux.posicion.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)[0].Trim();

                luVisitanteFinal.addObject(new FKLineup.CirclePlayer(jAux, 10, 10, 10, 10));
            }

            luInicialLocal.reorganizePlayers();
            luInicialVisitante.reorganizePlayers();
            luLocalFinal.reorganizePlayers();
            luVisitanteFinal.reorganizePlayers();

            lblEstado.Text = "Carga finalizada.";

            btnReproducir.Enabled = true;
        }

        private void generarHtml(ReportePartido rpt)
        {
            //Alineación Inicial Partido

            StringBuilder htmlTitularesInicio = new StringBuilder();

            if (rpt.titularesLocal.Count == 11 && rpt.titularesVisitante.Count == 11)
            {
                for (int i = 0; i < 11; i++)
                {
                    htmlTitularesInicio.Append("<tr style=\"height:25px;\">");
                    htmlTitularesInicio.Append("    <td style=\"width:50px;\">" + rpt.titularesLocal[i].posicion + "</td>");
                    htmlTitularesInicio.Append("    <td style=\"width:250px;\">" + rpt.titularesLocal[i].nombre + "</td>");
                    htmlTitularesInicio.Append("    <td style=\"width:20px;\">&nbsp;</td>");
                    htmlTitularesInicio.Append("    <td style=\"width:50px;\">" + rpt.titularesVisitante[i].posicion + "</td>");
                    htmlTitularesInicio.Append("    <td style=\"width:250px;\">" + rpt.titularesVisitante[i].nombre + "</td>");
                    htmlTitularesInicio.Append("</tr>");
                }
            }

            StringBuilder htmlSuplentesInicio = new StringBuilder();

            int maxSuplentes = Math.Max(rpt.suplentesLocal.Count, rpt.suplentesVisitante.Count);

            for (int i = 0; i < maxSuplentes; i++)
            {
                htmlSuplentesInicio.Append("<tr style=\"height:25px;\">");
                htmlSuplentesInicio.Append("    <td style=\"width:50px;\">" + (rpt.suplentesLocal.Count > i ? "S" : "&nbsp;") + "</td>");
                htmlSuplentesInicio.Append("    <td style=\"width:250px;\">" + (rpt.suplentesLocal.Count > i ? rpt.suplentesLocal[i].nombre : "&nbsp;") + "</td>");
                htmlSuplentesInicio.Append("    <td style=\"width:20px;\">&nbsp;</td>");
                htmlSuplentesInicio.Append("    <td style=\"width:50px;\">" + (rpt.suplentesVisitante.Count > i ? "S" : "&nbsp;") + "</td>");
                htmlSuplentesInicio.Append("    <td style=\"width:250px;\">" + (rpt.suplentesVisitante.Count > i ? rpt.suplentesVisitante[i].nombre : "&nbsp;") + "</td>");
                htmlSuplentesInicio.Append("</tr>");
            }

            //Alineación Final Partido

            StringBuilder htmlTitularesFin = new StringBuilder();

            if (rpt.titularesLocalFin.Count == 11 && rpt.titularesVisitanteFin.Count == 11)
            {
                for (int i = 0; i < 11; i++)
                {
                    htmlTitularesFin.Append("<tr style=\"height:25px;\">");
                    htmlTitularesFin.Append("    <td style=\"width:50px;\">" + rpt.titularesLocalFin[i].posicion + "</td>");
                    htmlTitularesFin.Append("    <td style=\"width:250px;\">" + rpt.titularesLocalFin[i].nombre + "</td>");
                    htmlTitularesFin.Append("    <td style=\"width:20px;\">&nbsp;</td>");
                    htmlTitularesFin.Append("    <td style=\"width:50px;\">" + rpt.titularesVisitanteFin[i].posicion + "</td>");
                    htmlTitularesFin.Append("    <td style=\"width:250px;\">" + rpt.titularesVisitanteFin[i].nombre + "</td>");
                    htmlTitularesFin.Append("</tr>");
                }
            }

            StringBuilder htmlSuplentesFin = new StringBuilder();

            for (int i = 0; i < maxSuplentes; i++)
            {
                htmlSuplentesFin.Append("<tr style=\"height:25px;\">");
                htmlSuplentesFin.Append("    <td style=\"width:50px;\">" + (rpt.suplentesLocalFin.Count > i ? rpt.suplentesLocalFin[i].posicion : "&nbsp;") + "</td>");
                htmlSuplentesFin.Append("    <td style=\"width:250px;\">" + (rpt.suplentesLocalFin.Count > i ? rpt.suplentesLocalFin[i].nombre : "&nbsp;") + "</td>");
                htmlSuplentesFin.Append("    <td style=\"width:20px;\">&nbsp;</td>");
                htmlSuplentesFin.Append("    <td style=\"width:50px;\">" + (rpt.suplentesVisitanteFin.Count > i ? rpt.suplentesVisitanteFin[i].posicion : "&nbsp;") + "</td>");
                htmlSuplentesFin.Append("    <td style=\"width:250px;\">" + (rpt.suplentesVisitanteFin.Count > i ? rpt.suplentesVisitanteFin[i].nombre : "&nbsp;") + "</td>");
                htmlSuplentesFin.Append("</tr>");
            }

            //Lista de Jugadas del Partido

            StringBuilder listaJugadas = new StringBuilder();

            bool sombreado = false;
            foreach (Ocasion oca in rpt.ocasiones)
            {
                if (sombreado)
                    listaJugadas.Append("<ul style=\"background-color: #f0f0f0; list-style:none; margin: 0; padding:2px 5px 10px 0px;\">");
                else
                    listaJugadas.Append("<ul style=\"background-color: #fff; list-style:none; margin: 0; padding:2px 5px 10px 0px;\">");

                listaJugadas.Append("<li style=\"font-weight:bold;\">Minuto " + oca.minuto + "</li>");

                foreach (string acc in oca.jugadas)
                {
                    listaJugadas.Append("<li>" + acc + "</li>");
                }

                listaJugadas.Append("</ul>");

                sombreado = !sombreado;
            }

            //Leemos las plantillas del reporte y las alineaciones
            string plantillaAlineacion = "";
            string plantillaReporte = "";

            try
            {
                StreamReader sr = null;

                sr = new StreamReader("temp\\plantilla-alineacion.html", Encoding.UTF8);
                plantillaAlineacion = sr.ReadToEnd();
                sr.Close();

                sr = new StreamReader("temp\\plantilla-reporte.html", Encoding.UTF8);
                plantillaReporte = sr.ReadToEnd();
                sr.Close();
            }
            catch (Exception)
            {
                MessageBox.Show("Error de lectura en plantillas.", "Error");
            }

            //Sustituimos los parámetros
            string htmlAlineacionInicio = "";
            string htmlAlineacionFinal = "";
            string htmlReporte = "";

            htmlAlineacionInicio = plantillaAlineacion.Replace("$$$equipo-local$$$", partidoPropio.campo.Equals("home") ? partidoPropio.nombrePropio : partidoPropio.nombreOponente);
            htmlAlineacionInicio = htmlAlineacionInicio.Replace("$$$equipo-visitante$$$", partidoPropio.campo.Equals("home") ? partidoPropio.nombreOponente : partidoPropio.nombrePropio);
            htmlAlineacionInicio = htmlAlineacionInicio.Replace("$$$titulares$$$", htmlTitularesInicio.ToString());
            htmlAlineacionInicio = htmlAlineacionInicio.Replace("$$$suplentes$$$", htmlSuplentesInicio.ToString());

            htmlReporte = plantillaReporte.Replace("$$$jugadas-partido$$$", listaJugadas.ToString());

            htmlAlineacionFinal = plantillaAlineacion.Replace("$$$equipo-local$$$", partidoPropio.campo.Equals("home") ? partidoPropio.nombrePropio : partidoPropio.nombreOponente);
            htmlAlineacionFinal = htmlAlineacionFinal.Replace("$$$equipo-visitante$$$", partidoPropio.campo.Equals("home") ? partidoPropio.nombreOponente : partidoPropio.nombrePropio);
            htmlAlineacionFinal = htmlAlineacionFinal.Replace("$$$titulares$$$", htmlTitularesFin.ToString());
            htmlAlineacionFinal = htmlAlineacionFinal.Replace("$$$suplentes$$$", htmlSuplentesFin.ToString());

            try
            {
                StreamWriter sw = null;

                sw = new StreamWriter("temp\\alineacion-inicial.html", false, Encoding.UTF8);
                sw.Write(htmlAlineacionInicio);
                sw.Close();

                sw = new StreamWriter("temp\\alineacion-final.html", false, Encoding.UTF8);
                sw.Write(htmlAlineacionFinal);
                sw.Close();

                sw = new StreamWriter("temp\\reporte.html", false, Encoding.UTF8);
                sw.Write(htmlReporte);
                sw.Close();
            }
            catch (Exception)
            {
                MessageBox.Show("Error de escritura en reporte del partido.", "Error");
            }
        }

        private void FrmVisorPartidos_Load(object sender, EventArgs e)
        {
            tabControl1.SelectedTab = tabPage1;
            tabControl1.SelectedTab = tabPage3;
            tabControl1.SelectedTab = tabPage4;
            tabControl1.SelectedTab = tabPage2;

            if (partidoPropio != null)
                tabControl1.TabPages.Remove(tabPage1);

            //Carga de la jornada
            bwWorkerCarga.RunWorkerAsync();
        }
    }
}
